Skip to content

Commit

Permalink
documenting pipelines, fixed issue with first block of circuitry crea…
Browse files Browse the repository at this point in the history
…ting a new pipeline stage instead of adding to previous
  • Loading branch information
sylefeb committed Mar 12, 2023
1 parent 0efdb07 commit b50d582
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 42 deletions.
55 changes: 52 additions & 3 deletions learn-silice/Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -1775,15 +1775,64 @@ come in handy.
A powerful construct is to define pipelines in [circuitries](#circuitry), which
can then be *concatenated* to a current pipeline.
Here is a simple example:
Here is [an example](../tests/circuits18.si):
```c
circuitry add_two(input i,output o)
{ // stage 1
uint8 v = i + 1;
->
// stage 2
o = v + 1;
->
}
unit main(output uint8 leds)
{
uint32 cycle=0;
uint8 a =0;
algorithm {
while (a<3) {
// stage 0
uint8 v = a;
__display("cycle %d, first stage, v=%d",cycle,v);
a = a + 1;
->
(v) = add_two(v); // adds two stages
// stage 3
v = v + 100;
->
// stage 4
__display("cycle %d, last stage, v=%d",cycle,v);
}
}
always_after { cycle = cycle + 1; }
}
```
The output is:
```
cycle 2, first stage, v= 0
cycle 3, first stage, v= 1
cycle 4, first stage, v= 2
cycle 6, last stage, v=102
cycle 7, last stage, v=103
cycle 8, last stage, v=104
```
Everything happens as if the content of the `add_two` circuitry had been cut and
pasted where it is instantiated, with two stage being added to the pipeline.
This is very convenient to defined pieces of pipelines to be added, for instance
a pipelined multiplier.
More advanced examples are in the raymarching pipeline
available in the [demo projects](../projects/vga_demo/vga_msponge.si).
An advanced example is the raymarching pipeline available in the
[demo projects](../projects/vga_demo/vga_msponge.si).
> **Note:** As a good practice suggestion, see how I indented the circuitry
instantiation to align with the pipelining arrows, indicating it does change the
pipeline.
> **Note:** A limitation of the current implementation is that a circuitry
containing a pipeline can only be instantiated within a parent pipeline using
at least one `->`. This will be fixed in the future.
## Pipelines in always blocks
Expand Down
6 changes: 3 additions & 3 deletions projects/vga_demo/vga_msponge.si
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@

$$if ECPIX5 then
$$ N_steps = 128
$$ delay = 45751
$$ delay = 45790
$$ VGA_1024_768 = 1
$$elseif DE10NANO then
$$ N_steps = 190
$$ delay = 93065
$$ delay = 93104
$$ VGA_1920_1080 = 1
$$elseif VERILATOR then
$$ N_steps = 64
$$ delay = 93191
$$ delay = 93230
$$ VGA_1920_1080 = 1
$$else
$$ error('sorry, this design is currently only for the ECPIX5 and de10-nano')
Expand Down
63 changes: 38 additions & 25 deletions src/Algorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2324,45 +2324,57 @@ Algorithm::t_combinational_block *Algorithm::concatenatePipeline(siliceParser::P
// go through the pipeline
// -> for each stage block
t_combinational_block *prev = _current;
bool first = (_current->context.pipeline_stage != nullptr); // if in an existing pipeline, start by adding to the last stage
for (auto b : pip->instructionList()) {
// create a fsm for the pipeline stage
t_fsm_nfo *fsm = new t_fsm_nfo;
fsm->name = "fsm_" + nfo->name + "_" + std::to_string(nfo->stages.size());
m_PipelineFSMs.push_back(fsm);
// stage info
t_pipeline_stage_nfo *snfo = new t_pipeline_stage_nfo();
snfo->pipeline = nfo;
snfo->fsm = fsm;
snfo->stage_id = (int)nfo->stages.size();
snfo->node = b;
// block context
t_combinational_block_context ctx = {
fsm, _current->context.subroutine, snfo,
nfo->stages.empty() ? _current : nfo->stages.back()->fsm->lastBlock,
nfo->stages.empty() ? _current->context.vio_rewrites : nfo->stages.back()->fsm->lastBlock->context.vio_rewrites
};
// add stage
nfo->stages.push_back(snfo);
// gather stage blocks (may recurse and concatenate other pipelines parts)
t_combinational_block *stage_start = addBlock("__stage_" + generateBlockName(), nullptr, &ctx, sourceloc(b));
fsm->firstBlock = stage_start;
fsm->parentBlock = _current;
t_fsm_nfo* fsm = nullptr;
t_pipeline_stage_nfo* snfo = nullptr;
t_combinational_block* from = nullptr;
if (first) {
// resume from previous
fsm = _current->context.pipeline_stage->fsm;
snfo = _current->context.pipeline_stage;
from = _current;
first = false;
} else {
// create a fsm for the pipeline stage
fsm = new t_fsm_nfo;
fsm->name = "fsm_" + nfo->name + "_" + std::to_string(nfo->stages.size());
m_PipelineFSMs.push_back(fsm);
// stage info
snfo = new t_pipeline_stage_nfo();
snfo->pipeline = nfo;
snfo->fsm = fsm;
snfo->stage_id = (int)nfo->stages.size();
snfo->node = b;
// block context
t_combinational_block_context ctx = {
fsm, _current->context.subroutine, snfo,
nfo->stages.empty() ? _current : nfo->stages.back()->fsm->lastBlock,
nfo->stages.empty() ? _current->context.vio_rewrites : nfo->stages.back()->fsm->lastBlock->context.vio_rewrites
};
// gather stage blocks (may recurse and concatenate other pipelines parts)
from = addBlock("__stage_" + generateBlockName(), nullptr, &ctx, sourceloc(b));
fsm->firstBlock = from;
fsm->parentBlock = _current;
// add stage
nfo->stages.push_back(snfo);
}
// gather the rest (note: stages may be recursively added in this call)
gather(b, stage_start, _context);
gather(b, from, _context);
// stage end is on last block
t_combinational_block *stage_end = fsm->lastBlock;
// -> check whether pipeline may contain fsms
if (_current->context.fsm == nullptr) {
// no, report an error if that is the case
if (!isStateLessGraph(stage_start)) {
if (!isStateLessGraph(from)) {
reportError(sourceloc(pip), "pipelines in always blocks cannot contain multiple states (they can in algorithms)");
}
fsm->firstBlock->is_state = false;
} else {
fsm->firstBlock->is_state = true; // make them all FSMs
}
// set next stage
prev->pipeline_next(stage_start, stage_end);
prev->pipeline_next(from, stage_end);
// advance
prev = nfo->stages.back()->fsm->lastBlock;
}
Expand Down Expand Up @@ -2536,6 +2548,7 @@ Algorithm::t_combinational_block *Algorithm::gatherPipeline(siliceParser::Pipeli
// yes: expand the parent pipeline
auto nfo = _current->context.pipeline_stage->pipeline;
return concatenatePipeline(pip, _current, _context, nfo);

}

}
Expand Down
28 changes: 17 additions & 11 deletions tests/circuits18.si
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
circuitry add_three(input i,output o)
circuitry add_two(input i,output o)
{
// stage 1
uint8 v = i + 1;
->
v = v + 1;
->
// stage 2
o = v + 1;
->
->
}

unit main(output uint8 leds)
{
uint32 cycle=0;
uint8 a =0;
algorithm {
while (a<16) {
uint8 v = a;
__display("cycle %d, first stage, v=%d",cycle,v);
a = a + 1;
(v) = add_three(v);
__display("cycle %d, last stage, v=%d",cycle,v);
}
while (a<3) {
// stage 0
uint8 v = a;
__display("cycle %d, first stage, v=%d",cycle,v);
a = a + 1;
->
(v) = add_two(v);
// stage 3
v = v + 100;
->
// stage 4
__display("cycle %d, last stage, v=%d",cycle,v);
}
}
always_after { cycle = cycle + 1; }
}

0 comments on commit b50d582

Please sign in to comment.