Socsim Generator is a co-simulation framework that enables automated integration of high-level simulators with the X-Heep System-on-Chip. Given a JSON configuration, it generates both the communication code for the X-Heep and the base code for the high-level simulator.
The generator currently supports co-simulations that use the following RISC-V protocols to communicate with the X-Heep: Open Bus Interface (OBI) and eXtension InterFace (XIF).
The Socsim Generator reads a JSON configuration file that describes the OBI peripheral's registers, memory map, and behavior. It then generates the necessary high-level code to implement the peripheral simulator, including register read/write handlers and memory access functions.
Similarly, for XIF coprocessors, the generator processes a JSON configuration that outlines the coprocessor's instruction set, registers, and interaction model. It produces the base code required to implement the coprocessor simulator.
The simulator configuration needs to be configured in a JSON file. The Socsim Generator can then be executed to produce the simulator code.
The overall JSON configuration structure is as follows:
| Field | Type | Description |
|---|---|---|
| project_name | string | Name of the project. |
| paths | object | Paths for X-Heep and output directory. |
| simulator_definitions | array | List of simulator definitions. |
| Field | Type | Description |
|---|---|---|
| xheep_dir | string | Path to the X-Heep installation directory. |
| output_dir | string | Path to the output directory for generated code. |
| Field | Type | Description |
|---|---|---|
| interface | string | Type of interface (e.g., "obi"). |
| identifier | string | Unique identifier for the simulator. |
| description | string | Description of the simulator. |
| class_name | string | Name of the simulator class. |
| target_language | string | Target programming language (e.g., "cpp"). |
| hardware_interface | object | Hardware interface details. |
| communication | object | Communication settings. |
| Field | Type | Description |
|---|---|---|
| memory_base_address | number | Base address of the peripheral's memory. |
| memory_size_bytes | number | Size of the peripheral's memory in bytes. |
| registers | array | List of register definitions. |
| Field | Type | Description |
|---|---|---|
| name | string | Name of the register. |
| direction_to_simulator | string | Direction of data flow ("input" or "output"). |
| type | string | Data type of the register (e.g., "logic"). |
| signed | boolean | Indicates if the register is signed. |
| width | number | Width of the register in bits. |
| default_value | number | Default value of the register. |
| description | string | Description of the register. |
| Field | Type | Description |
|---|---|---|
| name | string | Name of the custom instruction. |
| type | string | Type of instruction (e.g., "r", "i", "s"). |
| encoding | object | Encoding details (opcode, funct3, funct7). |
| operands | array | List of operand names. |
| operand_mapping | object | Mapping of operands to variable names. |
| cycles | number | Number of cycles the instruction takes (Currently does nothing). |
| memory_access | boolean | Indicates if the instruction accesses memory (Currently does nothing). |
NOTE: There is currently only support for R-type instructions.
| Field | Type | Description |
|---|---|---|
| opcode | string | Opcode of the instruction. |
| funct3 | string | funct3 field of the instruction. |
| funct7 | string | funct7 field of the instruction. |
| Field | Type | Description |
|---|---|---|
| host_address | string | Address for the host to connect to. |
| simulator_address | string | Address for the simulator to bind to. |
| send_timeout_ms | number | Timeout for sending messages in ms. |
| recv_timeout_ms | number | Timeout for receiving messages in ms. |
| retries | number | Number of retries for communication. |
The following is an example JSON configuration for generating an OBI peripheral simulator:
{
"project_name": "reimagined_simple_accelerator",
"paths": {
"xheep_dir": "/home/usr/x-heep",
"output_dir": "/home/usr/socsim-generator/examples"
},
"simulator_definitions": [
{
"interface": "obi",
"identifier": "reimagined_simple_accelerator",
"description": "A basic accelerator",
"class_name": "reimagined_simple_accelerator",
"target_language": "cpp",
"hardware_interface": {
"memory_base_address": 6000,
"memory_size_bytes": 100,
"registers": [
{ "name": "src_address", "direction_to_simulator": "input", "type": "logic", "signed": false, "width": 32, "default_value": 0, "description": "" },
{ "name": "dst_address", "direction_to_simulator": "input", "type": "logic", "signed": false, "width": 32, "default_value": 0, "description": "" },
{ "name": "threshold", "direction_to_simulator": "input", "type": "logic", "signed": false, "width": 16, "default_value": 0, "description": "" },
{ "name": "data_size", "direction_to_simulator": "input", "type": "logic", "signed": false, "width": 16, "default_value": 0, "description": "" }
]
},
"communication": {
"host_address": "tcp://localhost:5556",
"simulator_address": "tcp://*:5556",
"send_timeout_ms": 5000,
"recv_timeout_ms": 5000,
"retries": 3
}
}
]
}The following is an example JSON configuration for generating an XIF coprocessor simulator:
{
"project_name": "test_xif_accelerator",
"paths": {
"xheep_dir": "/home/usr/x-heep",
"output_dir": "/home/usr/socsim-generator/examples"
},
"simulator_definitions": [
{
"interface": "xif",
"identifier": "test_xif_accelerator",
"description": "An XIF accelerator for testing",
"class_name": "test_xif_accelerator",
"target_language": "cpp",
"hardware_interface": {
"memory_base_address": 6000,
"memory_size_bytes": 100,
"registers": [
{ "name": "rs1_val", "direction_to_simulator": "input", "type": "logic", "signed": false, "width": 32, "default_value": 0, "description": "" },
{ "name": "rs2_val", "direction_to_simulator": "input", "type": "logic", "signed": false, "width": 32, "default_value": 0, "description": "" },
{ "name": "instr", "direction_to_simulator": "input", "type": "logic", "signed": false, "width": 32, "default_value": 0, "description": "" },
{ "name": "result_val", "direction_to_simulator": "output", "type": "logic", "signed": false, "width": 32, "default_value": 0, "description": "" }
]
},
"custom_instructions": [
{ "name": "test_instruction",
"type": "r",
"encoding": { "opcode": "0b0001011", "funct3": "0b000", "funct7": "0b0000000"},
"operands": ["rd", "rs1", "rs2", "instr"],
"operand_mapping": { "rs1": "rs1_val", "rs2": "rs2_val", "rd": "result_val", "instr": "instr"},
"cycles": 1,
"memory_access": false
},
],
"communication": {
"host_address": "tcp://localhost:5556",
"simulator_address": "tcp://*:5556",
"send_timeout_ms": 5000,
"recv_timeout_ms": 5000,
"retries": 3
}
}
]
}This version of the Socsim Generator has some limitations:
- At each clock cycle, the framework performs both
sendandrecvoperations, regardless of whether new data needs to be transmitted. - Lack of interrupt support for the peripheral simulators. Instead of receiving a trigger when the simulator has completed its task, the processor must continuously poll the status register. This adds overhead since the processor wastes cycles checking for changes rather than performing useful work.
- It is tightly coupled to the X-Heep architecture.
- Replace the constant polling mechanism with an event-driven approach.
- Implement an interrupt-like behavior.
- Expand support to other System-on-Chip architectures beyond X-Heep.
