-
Notifications
You must be signed in to change notification settings - Fork 39
Add APB examples and fix APB pin level adapters #76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
1. Handle strobe signals correctly 2. Free the payload after usage to avoid deadlock 3. Remove redundant code
|
@JingJerYen THX for the PR. I need to review the code in more detail as these are significant changes. Did you run it with a verilated design? Or coupled with a Verilog simulator? |
| PENABLE_o.write(false); | ||
| PSELx_o.write(false); | ||
| if(trans->has_mm()) | ||
| trans->release(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line fixes the deadlock when running examples/apb
|
For this PR, I didn't run it with any RTL-level design. I just added the examples and found they didn't work, so I tried to fix the pin-level adapters. And the waveform was produced by examples/apb. I can add some comments on the code to explain some parts of the commit |
| } | ||
|
|
||
| template <unsigned DATA_WIDTH, unsigned ADDR_WIDTH> inline void initiator<DATA_WIDTH, ADDR_WIDTH>::bus_task() { | ||
| auto& hready = PREADY_i.read(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove the unused variable
| auto upper = addr_offset + trans->get_data_length(); | ||
| if(!PSTRB_o.get_interface() && addr_offset && upper != (DATA_WIDTH / 8)) { | ||
| SCCERR(SCMOD) << "Narrow accesses are not supported as there is no PSTRB signal! Skipping " << *trans; | ||
| if(!PSTRB_o.get_interface() && (addr_offset || upper != (DATA_WIDTH / 8))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I know, both start address and size should align with bus data width before APB4 where strobe signal hasn't been introduced, so I changed this line. Correct me if i'm wrong.
| tsckt->nb_transport_bw(*trans, phase, delay); | ||
| } else { | ||
| SCCDEBUG(SCMOD) << "Recv beg req for read to addr 0x" << std::hex << trans->get_address() << ", starting APB setup phase, "; | ||
| auto bytes_exp = scc::ilog2(trans->get_data_length()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are dead code, so i removed them
| data_t data{0}; | ||
| strb_t strb{0}; | ||
| // Handle TLM byte enables if present | ||
| if(trans->get_byte_enable_ptr() && trans->get_byte_enable_length() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add this part to handle TLM payload with byte_enable array , this is not handled in the original code
| if(PSTRB_o.get_interface()) | ||
| PSTRB_o.write(strb); | ||
| } else if(PSTRB_o.get_interface()) { | ||
| // From spec : For read transfers the bus master must drive all bits of PSTRB LOW |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spec states this
| tsckt->nb_transport_bw(*trans, phase, delay); | ||
| SCCDEBUG(SCMOD) << "Starting APB access phase"; | ||
| PENABLE_o.write(true); | ||
| wait(1_ps); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to be useless ?
| } else | ||
| for(size_t j = 0; j < DATA_WIDTH / 8; ++j) | ||
| *(trans->get_data_ptr() + j) = data(8 * j + 7, 8 * j).to_uint(); | ||
| wait(sc_core::SC_ZERO_TIME); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation makes it look to be significant changes, but actually only few lines are changed. It waits for PSEL signals here. And i think wait( zero_time) is more elegant than wait(1_ps) for the log message ?
| trans->set_read(); | ||
| } | ||
| sc_core::sc_time delay; | ||
| tlm::tlm_phase phase{tlm::BEGIN_REQ}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just the indentation changed.

I initially added an example for APB, but later found that the test didn’t work correctly due to several bugs. So I rewrote it to fix those issues.
Fix details:
Strobe signals were not handled properly — only consecutive 0xFF values were considered, but the APB spec does not guarantee they are contiguous.
A deadlock occurred due to a missing generic payload free.
Removed unused variables, redundant code, and replaced wait(1_ps) with wait(SC_ZERO_TIME).
The waveform below shows the correct behavior after applying this patch.