Files
PeakRDL-BusDecoder/src/peakrdl_busdecoder/module_tmpl.sv
Copilot 3d823572cc Fix nonconstant index errors in Questa by using unpacked structs and interface array intermediates (#17)
* Initial plan

* Fix nonconstant index error by using unpacked structs and arrays

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Add comprehensive tests for Questa compatibility with instance arrays

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Add intermediate signals for interface array fanin to fix Questa compatibility

Questa simulator rejects indexing interface arrays with non-constant variables in procedural blocks (always_comb). This fix creates intermediate unpacked array signals that are assigned from interface arrays using generate loops (with genvar), then references those intermediates in the fanin logic.

Changes:
- Added fanin_intermediate_gen.py to generate intermediate signals
- Modified APB3/APB4/AXI4-Lite cpuif classes to use intermediates for interface arrays
- Updated templates to include intermediate signal section
- Intermediate signals use genvar indexing (legal) instead of variable indexing (illegal in Questa)

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Fix type checking and formatting issues in fanin intermediate generator

- Added proper null checks for node.array_dimensions to avoid type errors
- Used getattr() to safely access is_interface and _interface attributes
- Added early returns when interface is None to prevent errors
- Fixed formatting issues in fanin_intermediate_gen.py
- All type checks now pass (only pre-existing errors remain in other files)
- All 67 tests still pass

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Fix test collection when cocotb is not installed

The cocotb test files (test_runner.py) have imports that fail at module level when cocotb is not installed, causing pytest collection to fail. This prevents running tests in environments without cocotb dependencies.

Solution: Updated conftest.py to conditionally ignore cocotb tests when cocotb is not available, allowing tests to pass in both environments (with and without cocotb).

- When cocotb is available: only ignore test_register_access.py files (existing behavior)
- When cocotb is not available: ignore all files under cocotb/** directories

This allows CI to run all 67 non-simulation tests successfully without requiring cocotb/verilator dependencies for basic testing.

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* add default for unpacked struct

* cocotb is test dependancy

* Refactor fanin intermediate signal logic to cpuif level

Moved the interface-specific signal assignment logic from fanin_intermediate_gen.py to individual cpuif classes (APB3Cpuif, APB4Cpuif, AXI4LiteCpuif). This follows better architecture principles where each cpuif knows which signals it needs.

Changes:
- Added fanin_intermediate_assignments() method to BaseCpuif
- Implemented fanin_intermediate_assignments() in APB3Cpuif, APB4Cpuif, and AXI4LiteCpuif
- Updated FaninIntermediateGenerator to call the cpuif method instead of checking interface type
- Removed interface type checking logic from fanin_intermediate_gen.py

This makes the code more maintainable and follows the single responsibility principle - each cpuif class knows its own signal requirements.

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>
2025-10-28 22:03:57 -07:00

80 lines
2.8 KiB
Systemverilog

//==========================================================
// Module: {{ds.module_name}}
// Description: CPU Interface Bus Decoder
// Author: PeakRDL-BusDecoder
// License: LGPL-3.0
// Date: {{current_date}}
// Version: {{version}}
// Links:
// - https://github.com/arnavsacheti/PeakRDL-BusDecoder
//==========================================================
module {{ds.module_name}}
{%- if cpuif.parameters %} #(
{{cpuif.parameters|join(",\n")|indent(4)}}
) {%- endif %} (
{{cpuif.port_declaration|indent(4)}}
);
//--------------------------------------------------------------------------
// CPU Bus interface logic
//--------------------------------------------------------------------------
logic cpuif_req;
logic cpuif_wr_en;
logic cpuif_rd_en;
logic [{{cpuif.addr_width-1}}:0] cpuif_wr_addr;
logic [{{cpuif.addr_width-1}}:0] cpuif_rd_addr;
logic cpuif_wr_ack;
logic cpuif_wr_err;
logic [{{cpuif.data_width-1}}:0] cpuif_wr_data;
logic [{{cpuif.data_width//8-1}}:0] cpuif_wr_byte_en;
logic cpuif_rd_ack;
logic cpuif_rd_err;
logic [{{cpuif.data_width-1}}:0] cpuif_rd_data;
//--------------------------------------------------------------------------
// Child instance signals
//--------------------------------------------------------------------------
{{cpuif_select|walk|indent(4)}}
cpuif_sel_t cpuif_wr_sel;
cpuif_sel_t cpuif_rd_sel;
//--------------------------------------------------------------------------
// Slave <-> Internal CPUIF <-> Master
//--------------------------------------------------------------------------
{{cpuif.get_implementation()|indent(4)}}
//--------------------------------------------------------------------------
// Write Address Decoder
//--------------------------------------------------------------------------
always_comb begin
// Default all write select signals to 0
cpuif_wr_sel = '{default: '0};
if (cpuif_req && cpuif_wr_en) begin
// A write request is pending
{{cpuif_decode|walk(flavor=cpuif_decode_flavor.WRITE)|indent(12)}}
end else begin
// No write request, all select signals remain 0
end
end
//--------------------------------------------------------------------------
// Read Address Decoder
//--------------------------------------------------------------------------
always_comb begin
// Default all read select signals to 0
cpuif_rd_sel = '{default: '0};
if (cpuif_req && cpuif_rd_en) begin
// A read request is pending
{{cpuif_decode|walk(flavor=cpuif_decode_flavor.READ)|indent(12)}}
end else begin
// No read request, all select signals remain 0
end
end
endmodule
{# (eof newline anchor) #}