Skip to content
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

[WIP] Error injection support for CC #457

Open
wants to merge 31 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1b3a3d4
added find_type() with platform iso ir as parameter
wvlothuizen Mar 25, 2022
4544a76
added initial check for consistency between platform function definit…
wvlothuizen Mar 25, 2022
e60ae4b
class Operands now supports vectors of integer and real operands
wvlothuizen Mar 25, 2022
cbfbacd
updated set of random functions
wvlothuizen Mar 25, 2022
c1ef3b9
Merge branch 'feature/cc/functions' into feature/cc/error-injection
wvlothuizen Mar 30, 2022
0a4eca6
WIP on annotating SourceLocation
wvlothuizen Mar 31, 2022
ddcb0b7
added 2 test cases
wvlothuizen Apr 4, 2022
c1197a3
Merge branch 'feature/cc/functions' into feature/cc/error-injection
wvlothuizen Apr 4, 2022
1e1fa98
Merge branch 'develop' of https://github.com/QE-Lab/OpenQL into featu…
wvlothuizen May 19, 2022
8bcc5cc
Merge branch 'feature/constant_propagation' into feature/cc/error-inj…
wvlothuizen May 19, 2022
8af66e1
renamed function rnd to rnd_bit, and added rnd (returning int)
wvlothuizen May 19, 2022
e8f0216
added rnd_range()
wvlothuizen May 20, 2022
0e8325d
Merge branch 'develop' of https://github.com/QE-Lab/OpenQL into featu…
wvlothuizen Jun 23, 2022
8746710
added extra types to platform, and small corrections to backend funct…
wvlothuizen Jun 24, 2022
0db0274
Merge branch 'develop' into feature/cc/error-injection
wvlothuizen Sep 8, 2022
e6da0b3
updated Changelog
wvlothuizen Sep 9, 2022
ea30290
added support for rnd_bit in PL, and manage rnd_adv for seq_out_sm
wvlothuizen Sep 16, 2022
a887266
added code generation for functions "rnd_*"
wvlothuizen Sep 19, 2022
f0fc2ce
Merge branch 'develop' of https://github.com/QE-Lab/OpenQL into featu…
wvlothuizen Sep 19, 2022
21f331d
disabled OPT_ANNOTATE_SOURCE_LOCATION (which is WIP and seems to make…
wvlothuizen Sep 19, 2022
51ee0b4
debugging CI failure nsome platforms ("RuntimeError: Container error:…
wvlothuizen Sep 19, 2022
833b042
CI attempt 2
wvlothuizen Sep 20, 2022
593db64
CI attempt 3
wvlothuizen Sep 20, 2022
21dba4d
CI attempt 4
wvlothuizen Sep 20, 2022
d8a1953
debugging CI, enabling instructions again, step 1
wvlothuizen Sep 20, 2022
cb255d7
Ateempt workaround
wvlothuizen Sep 20, 2022
f134aff
skip failing test on Ubuntu
wvlothuizen Sep 20, 2022
7904709
missing "@"
wvlothuizen Sep 20, 2022
175caa4
also excluded Macos
wvlothuizen Sep 21, 2022
e0d6ab1
cleanup
wvlothuizen Dec 9, 2022
e901b63
Merge branch 'develop' of https://github.com/QE-Lab/OpenQL into featu…
wvlothuizen Dec 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- integer values must be non-negative
- support for resource constrained scheduler
- creates .map file reporting measurement statements present in input, to allow retrieving measurements downstream
- support for Error Injection (conditional gates based on thresholded Pseudo Random Number Generator result)
- pass opt.ConstProp: constant propagator, replaces constant expressions by their result
- pass opt.DeadCodeElim: dead code eliminator, removes dead code, currently only unreachable if-branches

### Changed
- pass dec.Instructions: duration=0 in new-style decomposition rules now disables checking whether expansion fits, allowing automatic calculation of duration (and requiring scheduling after decomposition of such rules)
Expand Down
7 changes: 7 additions & 0 deletions include/ql/ir/ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ DataTypeLink add_type(const Ref &ir, Args... args) {
* Returns the data type with the given name, or returns an empty link if the
* type does not exist.
*/
DataTypeLink find_type(const ir::Platform &platform, const utils::Str &name);

/**
* Returns the data type with the given name, or returns an empty link if the
* type does not exist.
*/
// FIXME: this function only really needs ir->platform, similarly for several functions below
DataTypeLink find_type(const Ref &ir, const utils::Str &name);

/**
Expand Down
2 changes: 2 additions & 0 deletions src/ql/arch/cc/pass/gen/vq1asm/detail/backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ void Backend::codegen_block(const ir::BlockBaseRef &block, const Str &name, Int
codegen.block_start(name, depth);

// Loop over the statements and handle them individually.
//
// Functions that can throw an exception are wrapped in a try/catch to add context to the error message
for (const auto &stmt : block->statements) {

if (auto insn = stmt->as_instruction()) {
Expand Down
8 changes: 5 additions & 3 deletions src/ql/arch/cc/pass/gen/vq1asm/detail/bundle_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ enum class ConditionType {
// 1 operand:
UNARY, NOT,
// 2 operands
AND, NAND, OR, NOR, XOR, NXOR
AND, NAND, OR, NOR, XOR, NXOR,
// rnd_bit()
RND_BIT
};


struct tInstructionCondition {
public:
ConditionType cond_type;
utils::Vec<utils::UInt> cond_operands;
Str describe; // for annotation purposes
Str describe; // the original condition, for logging purposes
};


Expand All @@ -62,7 +64,7 @@ class BundleInfo {

// real-time measurement results: flag and operands
Bool isMeasRsltRealTime = false;
UInt breg_operand = 0; // the breg where the result is to be stored
UInt bregTargetMeasRsltRealTime = 0; // the breg where the result is to be stored

// original instruction, for logging purposes
Str describe;
Expand Down
63 changes: 43 additions & 20 deletions src/ql/arch/cc/pass/gen/vq1asm/detail/codegen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ static Str as_label(const Str &label) { return label + ":"; }
* Decode the expression for a conditional instruction into the old format as used for the API. Eventually this will have
* to be changed, but as long as the CC can handle expressions with 2 variables only this covers all we need.
*/
// FIXME: move to datapath
// FIXME: move to datapath?
// FIXME: redesign like handle_expression()
static tInstructionCondition decode_condition(const OperandContext &operandContext, const ir::ExpressionRef &condition) {
ConditionType cond_type;
utils::Vec<utils::UInt> cond_operands;
Expand Down Expand Up @@ -92,14 +93,13 @@ static tInstructionCondition decode_condition(const OperandContext &operandConte
QL_ICE("unsupported gate condition");
}
#if OPT_CC_USER_FUNCTIONS
// FIXME: note that is only here to allow playing around with function calls as condition. Real support
// requires a redesign
} else if (
fn->function_type->name == "rnd" ||
fn->function_type->name == "rnd_seed"
fn->function_type->name == "rnd_bit"
) {
cond_type = ConditionType::ALWAYS;
cond_type = ConditionType::RND_BIT;
cond_operands.push_back(fn->operands[0]->as_int_literal()->value); // FIXME: check.
QL_WOUT("FIXME: instruction condition function not yet handled: " + fn->function_type->name);
// FIXME: check profile
#endif
} else {
CHECK_COMPAT(fn->operands.size() == 2, "expected 2 operands");
Expand Down Expand Up @@ -274,7 +274,7 @@ Codegen::Codegen(const ir::Ref &ir, const OptionsRef &options)
, options(options)
, operandContext(ir)
, cs(operandContext)
, fncs(operandContext, dp, cs)
, fncs(*ir->platform, operandContext, dp, cs)
{
// NB: a new Backend is instantiated per call to compile, and
// as a result also a Codegen, so we don't need to cleanup
Expand Down Expand Up @@ -491,7 +491,7 @@ Codegen::CodeGenMap Codegen::collectCodeGenInfo(
};
#endif
// allocate SM bit for classic operand
UInt smBit = dp.allocateSmBit(bi.breg_operand, instrIdx);
UInt smBit = dp.allocateSmBit(bi.bregTargetMeasRsltRealTime, instrIdx);

// remind mapping of bit -> smBit for setting MUX
codeGenInfo.measResultRealTimeMap.emplace(group, MeasResultRealTimeInfo{smBit, resultBit, bi.describe});
Expand All @@ -516,8 +516,13 @@ void Codegen::bundle_finish(
CodeGenMap codeGenMap = collectCodeGenInfo(startCycle, durationInCycles);

// compute stuff requiring overview over all instruments:
// FIXME: add:
// - DSM used, for seq_inv_sm
UInt rnd_adv_all = 0; // mask of all PRNGs used (which need to advance to the next value)
for (UInt instrIdx = 0; instrIdx < settings.getInstrumentsSize(); instrIdx++) {
CodeGenInfo codeGenInfo = codeGenMap.at(instrIdx);
rnd_adv_all |= dp.getRndAdv(codeGenInfo.condGateMap);

// FIXME: add DSM used, for seq_inv_sm
}

// determine whether bundle has any real-time measurement results
Bool bundleHasMeasRsltRealTime = false;
Expand All @@ -542,6 +547,7 @@ void Codegen::bundle_finish(
if (codeGenInfo.instrHasOutput) {
emitOutput(
codeGenInfo.condGateMap,
rnd_adv_all,
codeGenInfo.digOut,
codeGenInfo.instrMaxDurationInCycles,
instrIdx,
Expand Down Expand Up @@ -675,10 +681,10 @@ void Codegen::custom_instruction(const ir::CustomInstruction &custom) {
throw;
}
}
if (ops.has_integer) {
if (ops.integers.size() > 0) {
QL_INPUT_ERROR("CC backend cannot handle integer operands yet");
}
if (ops.has_angle) {
if (ops.angles.size() > 0) {
QL_INPUT_ERROR("CC backend cannot handle real (angle) operands yet");
}

Expand Down Expand Up @@ -765,7 +771,7 @@ void Codegen::custom_instruction(const ir::CustomInstruction &custom) {
* note that Creg's are managed through a class, whereas bregs are just numbers
* - breg result (new)
*
* In the new IR (or, better said, in the new way "prototype"s for instruction operands van be defined
* In the new IR (or, better said, in the new way "prototype"s for instruction operands can be defined
* using access modes as described in
* https://openql.readthedocs.io/en/latest/gen/reference_configuration.html#instructions-section
* it is not well possible to specify a measurement that returns its result in a different bit than
Expand Down Expand Up @@ -793,11 +799,11 @@ void Codegen::custom_instruction(const ir::CustomInstruction &custom) {

// handle classic operand
if (ops.bregs.empty()) { // FIXME: currently always
bi.breg_operand = ops.qubits[0]; // implicit classic bit for qubit
QL_IOUT("using implicit bit " << bi.breg_operand << " for qubit " << ops.qubits[0]);
bi.bregTargetMeasRsltRealTime = ops.qubits[0]; // implicit classic bit for qubit
QL_IOUT("using implicit bit " << bi.bregTargetMeasRsltRealTime << " for qubit " << ops.qubits[0]);
} else { // FIXME: currently impossible
bi.breg_operand = ops.bregs[0];
QL_IOUT("using explicit bit " << bi.breg_operand << " for qubit " << ops.qubits[0]);
bi.bregTargetMeasRsltRealTime = ops.bregs[0];
QL_IOUT("using explicit bit " << bi.bregTargetMeasRsltRealTime << " for qubit " << ops.qubits[0]);
}
}

Expand Down Expand Up @@ -1084,7 +1090,7 @@ void Codegen::handle_expression(const ir::ExpressionRef &expression, const Str &
QL_ICE("expected reference to breg, but got: " << ir::describe(expression));
}
} else if (auto fn = expression->as_function_call()) {
// FIXME: handle (bit) cast?
// Note that the platform doesn't define a bit cast function

// handle the function
fncs.dispatch(fn, label_if_false, describe);
Expand Down Expand Up @@ -1114,6 +1120,17 @@ void Codegen::emitProgramStart(const Str &progName) {

cs.emit(".CODE"); // start .CODE section

#if OPT_CC_USER_FUNCTIONS
cs.emit("# random processor constants");
cs.emit(".DEF RND_REG_SEED_3 0 # Random number generator register: seed[127:96]");
cs.emit(".DEF RND_REG_SEED_2 1 # Random number generator register: seed[95:64]");
cs.emit(".DEF RND_REG_SEED_1 2 # Random number generator register: seed[63:32]");
cs.emit(".DEF RND_REG_SEED_0 3 # Random number generator register: seed[31:0]");
cs.emit(".DEF RND_REG_THRESHOLD 4 # Random number generator register: threshold");
cs.emit(".DEF RND_REG_RANGE 5 # Random number generator register: range");
cs.emit(".DEF RND_REG_VALUE 6 # Random number generator register: value");
#endif

// NB: new seq_bar semantics (firmware from 20191219 onwards)
comment("# synchronous start and latency compensation");
cs.emit("", "seq_bar", "", "# synchronization, delay set externally through SET_SEQ_BAR_CNT");
Expand Down Expand Up @@ -1193,6 +1210,7 @@ void Codegen::emitMeasRsltRealTime(

void Codegen::emitOutput(
const CondGateMap &condGateMap,
UInt rnd_adv_all,
tDigital digOut,
UInt instrMaxDurationInCycles,
UInt instrIdx,
Expand Down Expand Up @@ -1224,12 +1242,17 @@ void Codegen::emitOutput(
UInt smAddr = dp.emitPl(pl, condGateMap, instrIdx, slot);

// emit code for conditional gate
Str arg = QL_SS2S("S" << smAddr << "," << pl << "," << instrMaxDurationInCycles);
if (rnd_adv_all != 0) {
arg += QL_SS2S(",0x" << std::hex << rnd_adv_all);
}
cs.emit(
slot,
"seq_out_sm",
QL_SS2S("S" << smAddr << "," << pl << "," << instrMaxDurationInCycles),
QL_SS2S("# cycle " << startCycle << "-" << startCycle + instrMaxDurationInCycles << ": conditional code word/mask on '" << instrumentName << "'")
arg,
QL_SS2S("# cycle " << startCycle << "-" << startCycle + instrMaxDurationInCycles << ": conditional code word/mask on '" << instrumentName << "'") // FIXME: upfate comment for rnd_adv
);
// FIXME: also make this happen on instruments not involved now
}

// update lastEndCycle
Expand Down
7 changes: 1 addition & 6 deletions src/ql/arch/cc/pass/gen/vq1asm/detail/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,6 @@ class Codegen {
void handle_expression(const ir::ExpressionRef &expression, const Str &label_if_false, const Str &descr); // FIXME: private?


protected:
// FIXME: split off emitting into separate class
// friend class Functions; // needs access to emit*()


private: // types
/**
* Code generation info for single instrument.
Expand Down Expand Up @@ -195,7 +190,7 @@ class Codegen {
void emitProgramStart(const Str &progName);
void emitProgramFinish();
void emitMeasRsltRealTime(const MeasResultRealTimeMap &measResultRealTimeMap, UInt instrIdx, UInt startCycle, Int slot, const Str &instrumentName);
void emitOutput(const CondGateMap &condGateMap, tDigital digOut, UInt instrMaxDurationInCycles, UInt instrIdx, UInt startCycle, Int slot, const Str &instrumentName);
void emitOutput(const CondGateMap &condGateMap, UInt rnd_adv_all, tDigital digOut, UInt instrMaxDurationInCycles, UInt instrIdx, UInt startCycle, Int slot, const Str &instrumentName);
void emitPadToCycle(UInt instrIdx, UInt startCycle, Int slot, const Str &instrumentName);

// generic helpers
Expand Down
1 change: 1 addition & 0 deletions src/ql/arch/cc/pass/gen/vq1asm/detail/codesection.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define NUM_RSRVD_CREGS 2 // must match number of REG_TMP*
#define NUM_CREGS (64-NUM_RSRVD_CREGS) // starting from R0
#define NUM_BREGS 1024 // bregs require mapping to DSM, which introduces holes, so we probably fail before we reach this limit
#define NUM_RND 8 // must match HDL

namespace ql {
namespace arch {
Expand Down
41 changes: 32 additions & 9 deletions src/ql/arch/cc/pass/gen/vq1asm/detail/datapath.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ UInt Datapath::allocateSmBit(UInt breg_operand, UInt instrIdx) {
// - DSM size is 1024 bits (128 bytes)
// Other notes:
// - we don't attempt to be smart about DSM transfer size allocation
// - new allocations to the same breg_operand overwrite the old mapping
// - new allocations to the same breg overwrite the old mapping
// - we don't reuse SM bits (thus wasting space)

UInt smBit = 0;
Expand All @@ -61,11 +61,11 @@ UInt Datapath::allocateSmBit(UInt breg_operand, UInt instrIdx) {

auto it = mapBregToSmBit.find(breg_operand);
if (it != mapBregToSmBit.end()) {
QL_IOUT("overwriting mapping of breg_operand " << it->second);
QL_IOUT("overwriting mapping of breg " << it->second);
}
}

QL_IOUT("mapping breg_operand " << breg_operand << " to smBit " << smBit);
QL_IOUT("mapping breg " << breg_operand << " to smBit " << smBit);
mapBregToSmBit.set(breg_operand) = smBit; // created on demand

smBitLastInstrIdx = instrIdx;
Expand All @@ -74,16 +74,15 @@ UInt Datapath::allocateSmBit(UInt breg_operand, UInt instrIdx) {
return smBit;
}

// NB: bit_operand can be breg_operand or cond_operand, depending on context of caller. FIXME: cond_operand no longer exists,update identifiers and strings
UInt Datapath::getSmBit(UInt bit_operand) const {
UInt Datapath::getSmBit(UInt breg) const {
UInt smBit;

auto it = mapBregToSmBit.find(bit_operand);
auto it = mapBregToSmBit.find(breg);
if (it != mapBregToSmBit.end()) {
smBit = it->second;
QL_DOUT("found mapping: bit_operand " << bit_operand << " to smBit " << smBit);
QL_DOUT("found mapping: breg " << breg << " to smBit " << smBit);
} else {
QL_INPUT_ERROR("Request for DSM bit of bit_operand " << bit_operand << " that was never assigned by measurement"); // NB: message refers to user perspective (and thus calling semantics)
QL_INPUT_ERROR("Request for DSM bit of breg " << breg << " that was never assigned by measurement"); // NB: message refers to user perspective (and thus calling semantics)
}
return smBit;
}
Expand Down Expand Up @@ -172,11 +171,30 @@ UInt Datapath::getMuxSmAddr(const MeasResultRealTimeMap &measResultRealTimeMap)
}


UInt Datapath::getRndAdv(const CondGateMap &condGateMap) {
UInt rnd_adv = 0; // mask of PRNGs used

for (auto &cg : condGateMap) {
Int group = cg.first;
CondGateInfo cgi = cg.second;

if (cgi.instructionCondition.cond_type == ConditionType::RND_BIT) {
UInt prng = cgi.instructionCondition.cond_operands[0];
rnd_adv |= 1UL<<prng; // FIXME: rnd_adv must be identical on all instruments, irrespective of local use
}
}

return rnd_adv;
}


// FIXME: split like emitMux/getMuxSmAddr
// returns: SM address
UInt Datapath::emitPl(UInt pl, const CondGateMap &condGateMap, UInt instrIdx, Int slot) {
Bool minMaxValid = false; // we might not access SM
UInt minSmBit = MAX;
UInt maxSmBit = 0;
UInt rnd_adv = 0; // mask of PRNGs used

if (condGateMap.empty()) {
QL_ICE("condGateMap must not be empty");
Expand All @@ -197,7 +215,7 @@ UInt Datapath::emitPl(UInt pl, const CondGateMap &condGateMap, UInt instrIdx, In
<< ", condition='" << cgi.instructionCondition.describe << "'")
);

// shorthand
// helper lambda
auto winBit = [this, cgi, &minMaxValid, &minSmBit, &maxSmBit](int i)
{
UInt smBit = getSmBit(cgi.instructionCondition.cond_operands[i]);
Expand Down Expand Up @@ -248,6 +266,11 @@ UInt Datapath::emitPl(UInt pl, const CondGateMap &condGateMap, UInt instrIdx, In
case ConditionType::XOR:
rhs << "SM[" << winBit(0) << "] ^ SM[" << winBit(1) << "]";
break;

case ConditionType::RND_BIT:
UInt prng = cgi.instructionCondition.cond_operands[0];
rhs << "RND[" << prng << "]";
break;
}

// emit PL logic
Expand Down
3 changes: 2 additions & 1 deletion src/ql/arch/cc/pass/gen/vq1asm/detail/datapath.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,13 @@ class Datapath {
void programFinish();

UInt allocateSmBit(UInt breg_operand, UInt instrIdx);
UInt getSmBit(UInt bit_operand) const;
UInt getSmBit(UInt breg) const;
UInt getOrAssignMux(UInt instrIdx, const MeasResultRealTimeMap &measResultRealTimeMap);
UInt getOrAssignPl(UInt instrIdx, const CondGateMap &condGateMap);
static UInt getSizeTag(UInt numReadouts);
void emitMux(Int mux, const MeasResultRealTimeMap &measResultRealTimeMap, Int slot);
static UInt getMuxSmAddr(const MeasResultRealTimeMap &measResultRealTimeMap);
UInt getRndAdv(const CondGateMap &condGateMap);
UInt emitPl(UInt pl, const CondGateMap &condGateMap, UInt instrIdx, Int slot);

Str getDatapathSection() const { return datapathSection.str(); }
Expand Down
Loading